/*
组合模式（Composite Pattern）是一种结构型设计模式，它允许我们将对象组合成树形结构来表示“部分-整体”的层次结构。
组合模式使得客户端可以统一对待单个对象和组合对象，从而使得用户对单个对象和组合对象的使用具有一致性。

在组合模式中，有以下几个角色：

● 组件（Component）：定义了组合对象和叶子对象的共同接口，并提供默认的实现。
● 叶子对象（Leaf）：表示组合的叶子节点，它没有子节点。
● 组合对象（Composite）：表示组合的中间节点，它可以包含子节点。
● 客户端（Client）：使用组合对象和叶子对象的接口。

下面是一个使用组合模式的C语言例程，用于实现一个文件系统的树形结构，其中文件夹和文件都是组合对象，文件夹可以包含文件夹和文件，文件只能包含文件内容：
*/

#include <stdio.h>
#include <stdlib.h>

// 组件接口
typedef struct
{
    char *name;
    void (*print)();
} Component;

// 叶子对象
typedef struct
{
    Component component;
    char *content;
    void (*print)();
} File;

// 组合对象
typedef struct
{
    Component component;
    Component **children;
    int childCount;
    void (*add)();
    void (*remove)();
    void (*print)();
} Folder;

// 叶子对象的方法实现
void printFile(File *file)
{
    // File *file = (File *)malloc(sizeof(File));
    printf("File: %s\n", file->component.name);
    printf("Content: %s\n", file->content);
}

// 组合对象的方法实现
void addComponent(Component *component, Component *child)
{
    Folder *folder = (Folder *)component;
    folder->children[folder->childCount++] = child;
}

void removeComponent(Component *component, Component *child)
{
    Folder *folder = (Folder *)component;
    int i;
    for (i = 0; i < folder->childCount; i++)
    {
        if (folder->children[i] == child)
        {
            int j;
            for (j = i; j < folder->childCount - 1; j++)
            {
                folder->children[j] = folder->children[j + 1];
            }
            folder->childCount--;
            break;
        }
    }
}

void printFolder(Folder *folder)
{
    // Folder *folder = (Folder *)malloc(sizeof(Folder));
    printf("Folder: %s\n", folder->component.name);
    int i;
    for (i = 0; i < folder->childCount; i++)
    {
        folder->children[i]->print(folder->children[i]);
    }
}

int main()
{
    // 创建文件和文件夹
    File file1;
    file1.component.name = "file1.txt";
    file1.content = "This is file1 content";
    file1.component.print = printFile;

    File file2;
    file2.component.name = "file2.txt";
    file2.content = "This is file2 content";
    file2.component.print = printFile;

    Folder folder1;
    folder1.component.name = "folder1";
    folder1.children = (Component **)malloc(sizeof(Component *) * 2);
    folder1.childCount = 0;
    folder1.component.print = printFolder;

    Folder folder2;
    folder2.component.name = "folder2";
    folder2.children = (Component **)malloc(sizeof(Component *) * 1);
    folder2.childCount = 0;
    folder2.component.print = printFolder;

    // 构建文件系统树形结构
    addComponent((Component *)&folder1, (Component *)&file1);
    addComponent((Component *)&folder1, (Component *)&folder2);
    addComponent((Component *)&folder2, (Component *)&file2);
    // removeComponent((Component *)&folder1, (Component *)&folder2);
    // addComponent((Component *)&folder1, (Component *)&file2);

    // 使用组合对象和叶子对象的接口
    folder1.component.print(&folder1);

    return 0;
}

/*
在上面的例程中，首先定义了组件接口Component，其中声明了打印的接口方法。
然后，实现了叶子对象File，其中包含了文件的内容，并实现了打印的方法。
接下来，实现了组合对象Folder，其中维护了一个子节点的数组，并实现了添加、删除和打印的方法。
在main函数中，创建了文件和文件夹对象，并构建了文件系统的树形结构。
最后，使用组合对象的接口方法来打印整个文件系统的结构。

通过使用组合模式，我们可以将对象组合成树形结构，从而表示“部分-整体”的层次结构。
这样可以使得客户端可以统一对待单个对象和组合对象，从而使得用户对单个对象和组合对象的使用具有一致性。
同时，组合模式也使得系统的结构更清晰，增加了系统的灵活性和可扩展性。
*/